package org.jeecg.modules.mes.service.impl;

import java.util.List;
import java.util.Date;
import java.math.BigDecimal;

import org.jeecg.modules.mes.entity.MesEmployeePieceWage;
import org.jeecg.modules.mes.entity.MesProductionPlanTask;
import org.jeecg.modules.mes.entity.MesPieceRateStandard;
import org.jeecg.modules.mes.entity.MesProductionPlan;
import org.jeecg.modules.mes.mapper.MesEmployeePieceWageMapper;
import org.jeecg.modules.mes.service.IMesEmployeePieceWageService;
import org.jeecg.modules.mes.service.IMesProductionPlanTaskService;
import org.jeecg.modules.mes.service.IMesPieceRateStandardService;
import org.jeecg.modules.mes.service.IMesProductionPlanService;
import org.jeecg.modules.mes.service.IMesTaskParticipantService;
import org.jeecg.modules.mes.entity.MesTaskParticipant;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Description: 员工计件工资记录表
 * @Author: jeecg-boot
 * @Date: 2025-01-01
 * @Version: V1.0
 */
@Service
@Slf4j
public class MesEmployeePieceWageServiceImpl extends ServiceImpl<MesEmployeePieceWageMapper, MesEmployeePieceWage> implements IMesEmployeePieceWageService {

    @Autowired
    private MesEmployeePieceWageMapper employeePieceWageMapper;

    @Autowired
    private IMesProductionPlanTaskService taskService;

    @Autowired
    private IMesPieceRateStandardService pieceRateStandardService;

    @Autowired
    private IMesProductionPlanService productionPlanService;

    @Autowired
    private IMesTaskParticipantService taskParticipantService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MesEmployeePieceWage calculatePieceWage(String taskId, String employeeId, Integer completedQuantity) {
        return calculatePieceWageWithBonus(taskId, employeeId, completedQuantity, null, null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MesEmployeePieceWage calculatePieceWageWithBonus(String taskId, String employeeId, 
                                                          Integer completedQuantity, 
                                                          BigDecimal qualityScore, 
                                                          BigDecimal efficiencyScore) {
        try {
            // 1. 获取任务信息
            MesProductionPlanTask task = taskService.getById(taskId);
            if (task == null) {
                log.error("任务不存在: taskId={}", taskId);
                return null;
            }

            // 2. 获取生产计划信息
            MesProductionPlan plan = productionPlanService.getById(task.getPlanId());
            if (plan == null) {
                log.error("生产计划不存在: planId={}", task.getPlanId());
                return null;
            }

            // 3. 从产品信息中提取产品类别（使用productInfo的第一部分作为产品类别）
            String productCategory = "DEFAULT";
            if (plan.getProductInfo() != null && !plan.getProductInfo().isEmpty()) {
                String[] parts = plan.getProductInfo().split("-");
                if (parts.length > 0) {
                    productCategory = parts[0].trim();
                }
            }

            // 4. 获取计件标准
            MesPieceRateStandard rateStandard = pieceRateStandardService.getRateStandard(
                task.getWorkTypeId(), productCategory);
            
            if (rateStandard == null) {
                log.warn("未找到计件标准: workTypeId={}, productCategory={}", 
                    task.getWorkTypeId(), productCategory);
                return null;
            }

            // 5. 计算基础工资
            BigDecimal baseWage = rateStandard.getBaseRate()
                .multiply(BigDecimal.valueOf(completedQuantity))
                .multiply(rateStandard.getDifficultyFactor());

            // 6. 计算质量奖金
            BigDecimal qualityBonus = BigDecimal.ZERO;
            if (qualityScore != null && qualityScore.compareTo(BigDecimal.valueOf(80)) > 0) {
                qualityBonus = baseWage.multiply(rateStandard.getQualityBonusRate())
                    .multiply(qualityScore.subtract(BigDecimal.valueOf(80)))
                    .divide(BigDecimal.valueOf(20), 2, BigDecimal.ROUND_HALF_UP);
            }

            // 7. 计算效率奖金
            BigDecimal efficiencyBonus = BigDecimal.ZERO;
            if (efficiencyScore != null && efficiencyScore.compareTo(BigDecimal.valueOf(100)) > 0) {
                efficiencyBonus = baseWage.multiply(rateStandard.getEfficiencyBonusRate())
                    .multiply(efficiencyScore.subtract(BigDecimal.valueOf(100)))
                    .divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP);
            }

            // 8. 计算总工资
            BigDecimal totalWage = baseWage.add(qualityBonus).add(efficiencyBonus);

            // 9. 创建工资记录
            MesEmployeePieceWage wageRecord = new MesEmployeePieceWage();
            wageRecord.setEmployeeId(employeeId);
            
            // 通过参与者表获取员工姓名
            MesTaskParticipant participant = taskParticipantService.checkEmployeeParticipation(taskId, employeeId);
            wageRecord.setEmployeeName(participant != null ? participant.getEmployeeName() : "");
            wageRecord.setTaskId(taskId);
            wageRecord.setPlanId(task.getPlanId());
            wageRecord.setWorkTypeId(task.getWorkTypeId());
            wageRecord.setWorkTypeName(task.getWorkTypeName());
            wageRecord.setProductCode(productCategory);
            wageRecord.setProductName(plan.getProductInfo());
            wageRecord.setCompletedQuantity(completedQuantity);
            wageRecord.setPieceRate(rateStandard.getBaseRate());
            wageRecord.setBaseWage(baseWage);
            wageRecord.setQualityBonus(qualityBonus);
            wageRecord.setEfficiencyBonus(efficiencyBonus);
            wageRecord.setTotalWage(totalWage);
            wageRecord.setWorkDate(new Date());
            wageRecord.setSettlementStatus(0); // 未结算

            // 10. 保存工资记录
            this.save(wageRecord);

            log.info("计件工资计算完成: employeeId={}, taskId={}, totalWage={}", 
                employeeId, taskId, totalWage);

            return wageRecord;
        } catch (Exception e) {
            log.error("计算计件工资失败: taskId={}, employeeId={}", taskId, employeeId, e);
            throw new RuntimeException("计算计件工资失败", e);
        }
    }

    @Override
    public List<MesEmployeePieceWage> getEmployeeWageStats(String employeeId, Date startDate, Date endDate) {
        try {
            return employeePieceWageMapper.getEmployeeWageStats(employeeId, startDate, endDate);
        } catch (Exception e) {
            log.error("获取员工工资统计失败: employeeId={}", employeeId, e);
            return null;
        }
    }

    @Override
    public List<MesEmployeePieceWage> getDailyWageByEmployee(String employeeId, Date workDate) {
        try {
            return employeePieceWageMapper.getDailyWageByEmployee(employeeId, workDate);
        } catch (Exception e) {
            log.error("获取员工日工资统计失败: employeeId={}, workDate={}", employeeId, workDate, e);
            return null;
        }
    }

    @Override
    public List<MesEmployeePieceWage> getWageRecordsByTask(String taskId) {
        try {
            return employeePieceWageMapper.getWageRecordsByTask(taskId);
        } catch (Exception e) {
            log.error("获取任务工资记录失败: taskId={}", taskId, e);
            return null;
        }
    }

    @Override
    public List<MesEmployeePieceWage> getPendingSettlementWages(String employeeId) {
        try {
            return employeePieceWageMapper.getPendingSettlementWages(employeeId);
        } catch (Exception e) {
            log.error("获取待结算工资记录失败: employeeId={}", employeeId, e);
            return null;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchSettleWages(List<String> wageIds) {
        try {
            UpdateWrapper<MesEmployeePieceWage> updateWrapper = new UpdateWrapper<>();
            updateWrapper.in("id", wageIds);
            updateWrapper.set("settlement_status", 1);
            updateWrapper.set("settlement_time", new Date());
            
            return this.update(updateWrapper);
        } catch (Exception e) {
            log.error("批量结算工资失败: wageIds={}", wageIds, e);
            return false;
        }
    }

    @Override
    public BigDecimal getTotalWageByEmployee(String employeeId, Date startDate, Date endDate) {
        try {
            QueryWrapper<MesEmployeePieceWage> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("employee_id", employeeId);
            if (startDate != null) {
                queryWrapper.ge("work_date", startDate);
            }
            if (endDate != null) {
                queryWrapper.le("work_date", endDate);
            }
            
            List<MesEmployeePieceWage> wageRecords = this.list(queryWrapper);
            
            return wageRecords.stream()
                .map(MesEmployeePieceWage::getTotalWage)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        } catch (Exception e) {
            log.error("获取员工工资汇总失败: employeeId={}", employeeId, e);
            return BigDecimal.ZERO;
        }
    }
}
